import path from "node:path";
import fs from "node:fs";
import json5 from "json5";
import { compose, flip, lensProp, mergeDeepLeft, view } from "ramda";
import { GlobalConfig, GlobalDefaultConfig } from "./default-cnf/global.default.config";
import { logger } from "./log.config";
import * as protobuf from "protobufjs";
import { getProjectDir } from "../utils/app.util";
import { CmdParams } from "../task/cmd/cmd.params";

/**
 * 获取配置文件路径
 * @param filename
 */
const getConfigFile = (filename: string) => {
  return getProjectDir("", filename);
};

/**
 * 加载配置
 * 1. 将默认配置和自定义配置合并
 * 2. 默认配置文件 {@link GlobalDefaultConfig}
 * 3. 自定义配置文件 和 server.js 同级目录下 application.config.json5
 */
const loadConfig = (): GlobalConfig => {
  const defaultConfig = GlobalDefaultConfig();
  try {
    const configPath = CmdParams.params.config || getConfigFile("application.config.json5");
    if (fs.existsSync(configPath!)) {
      const json5Str = fs.readFileSync(configPath!, "utf-8");
      if (configPath.endsWith("json5")) {
      }
      return mergeDeepLeft(
        configPath.endsWith("json5") ? json5.parse(json5Str) : JSON.parse(json5Str),
        defaultConfig,
      );
    }
  } catch (e) {
    logger.error("load config error", e);
  }
  return defaultConfig;
};

/**
 * 全局配置
 */
export const appConfig = compose<[], GlobalConfig, Readonly<GlobalConfig>>(
  Object.freeze,
  loadConfig,
)();

export interface GlobalScreenTokens {
  [field: string]: string;
}

// 屏幕token相关文件名
const screenTokenFilename = "screen.token.json";

/**
 * 加载屏幕token
 */
export const loadScreenTokens = (): GlobalScreenTokens => {
  try {
    let configPath = getConfigFile(screenTokenFilename);
    if (CmdParams.params.config) {
      configPath = CmdParams.params.config.replace("config.json", "screen.token.json");
    }
    if (fs.existsSync(configPath!)) {
      const jsonStr = fs.readFileSync(configPath!, "utf-8");
      return JSON.parse(jsonStr) as GlobalScreenTokens;
    }
  } catch (e) {
    logger.error("load screen tokens error", e);
  }
  return {} as GlobalScreenTokens;
};

/**
 * 读取屏幕token
 */
export const readScreenTokens1 = compose(flip(view)(loadScreenTokens()), lensProp as any) as (
  screenId: string,
) => string | undefined;

let screenTokens: any = {};

export const readScreenTokens = (screenId: string) => {
  return screenTokens[screenId];
};

const refreshTokens = () => {
  screenTokens = loadScreenTokens();
};

refreshTokens();

/**
 * 保存屏幕token
 * @param tokens
 */
export const saveScreenTokens = (tokens: GlobalScreenTokens) => {
  try {
    let configPath = getConfigFile(screenTokenFilename);
    if (CmdParams.params.config) {
      configPath = CmdParams.params.config.replace("config.json", "screen.token.json");
    }
    fs.writeFileSync(configPath!, JSON.stringify(tokens, null, 2));
    refreshTokens();
  } catch (e) {
    logger.error("save screen tokens error", e);
    throw e;
  }
};

const protoPath = path.join(__dirname, "./default-cnf/sr_pro.proto");

const protoContent = fs.readFileSync(protoPath, "utf-8");

export const srProtoBufRoot = protobuf.parse(protoContent).root;
export const srProtoBufDeviceAlert = srProtoBufRoot.lookupType("SRMQTTDeviceAlert");
export const srProtoBufString = srProtoBufRoot.lookupType("SRMQTTString");
